import * as fs from 'fs-extra';
import { ComponentProp, ComponentEvent, ComponentSlot, ComponentMethod } from '../core/types';

/**
 * 代码分析器
 * 用于从Vue组件代码中提取更多隐含信息
 */
export class CodeAnalyzer {
  /**
   * 分析组件代码
   * @param content 组件文件内容
   * @param isVue3 是否为Vue 3组件
   */
  public analyze(content: string, isVue3: boolean): {
    props: ComponentProp[];
    events: ComponentEvent[];
    slots: ComponentSlot[];
    methods: ComponentMethod[];
  } {
    // 提取各部分内容
    const templateContent = this.extractTemplate(content);
    const scriptContent = this.extractScript(content);
    
    // 初始化返回结果
    const result = {
      props: [] as ComponentProp[],
      events: [] as ComponentEvent[],
      slots: [] as ComponentSlot[],
      methods: [] as ComponentMethod[]
    };
    
    // 分析各部分
    if (templateContent) {
      this.analyzeTemplate(templateContent, result, isVue3);
    }
    
    if (scriptContent) {
      this.analyzeScript(scriptContent, result, isVue3);
    }
    
    return result;
  }
  
  /**
   * 提取模板内容
   */
  private extractTemplate(content: string): string | null {
    const match = content.match(/<template>([\s\S]*?)<\/template>/);
    return match ? match[1] : null;
  }
  
  /**
   * 提取脚本内容
   */
  private extractScript(content: string): string | null {
    const match = content.match(/<script( setup)?>([\s\S]*?)<\/script>/);
    return match ? match[2] : null;
  }
  
  /**
   * 分析模板内容
   */
  private analyzeTemplate(
    templateContent: string, 
    result: {
      props: ComponentProp[];
      events: ComponentEvent[];
      slots: ComponentSlot[];
      methods: ComponentMethod[];
    },
    isVue3: boolean
  ): void {
    // 查找插槽定义
    this.extractSlotsFromTemplate(templateContent, result.slots);
    
    // 查找属性使用情况
    this.extractPropsUsageFromTemplate(templateContent, result.props, isVue3);
    
    // 查找事件触发
    this.extractEventsFromTemplate(templateContent, result.events, isVue3);
  }
  
  /**
   * 从模板中提取插槽定义
   */
  private extractSlotsFromTemplate(templateContent: string, slots: ComponentSlot[]): void {
    // 查找所有插槽标签
    const slotMatches = templateContent.match(/<slot\b[^>]*>/g);
    if (!slotMatches) return;
    
    slotMatches.forEach(slotTag => {
      // 提取插槽名称
      const nameMatch = slotTag.match(/name\s*=\s*["']([^"']+)["']/);
      const slotName = nameMatch ? nameMatch[1] : 'default';
      
      // 检查是否已存在
      const existingSlot = slots.find(s => s.name === slotName);
      if (existingSlot) return;
      
      // 创建新插槽
      const newSlot: ComponentSlot = {
        name: slotName,
        description: slotName === 'default' ? '默认插槽' : `${slotName}插槽`,
        bindings: []
      };
      
      // 提取绑定变量
      const bindingsMatch = slotTag.match(/:[^=]+\s*=\s*["'][^"']+["']/g);
      if (bindingsMatch) {
        bindingsMatch.forEach(binding => {
          const bindingMatch = binding.match(/:([^=]+)\s*=\s*["']([^"']+)["']/);
          if (bindingMatch) {
            newSlot.bindings.push({
              name: bindingMatch[1].trim(),
              type: 'any',
              description: ''
            });
          }
        });
      }
      
      slots.push(newSlot);
    });
  }
  
  /**
   * 从模板中提取属性使用情况
   */
  private extractPropsUsageFromTemplate(
    templateContent: string, 
    props: ComponentProp[], 
    isVue3: boolean
  ): void {
    // 查找条件渲染指令
    this.extractPropsFromConditionals(templateContent, props, isVue3);
    
    // 查找循环渲染指令
    this.extractPropsFromLoops(templateContent, props, isVue3);
    
    // 查找属性绑定
    this.extractPropsFromBindings(templateContent, props, isVue3);
  }
  
  /**
   * 从条件渲染指令中提取属性信息
   */
  private extractPropsFromConditionals(
    templateContent: string, 
    props: ComponentProp[], 
    isVue3: boolean
  ): void {
    // v-if, v-else-if, v-show 指令
    const conditionalMatches = templateContent.match(/v-(if|else-if|show)\s*=\s*["']([^"']+)["']/g);
    if (!conditionalMatches) return;
    
    conditionalMatches.forEach(directive => {
      const match = directive.match(/v-(if|else-if|show)\s*=\s*["']([^"']+)["']/);
      if (!match) return;
      
      const condition = match[2];
      
      // 解析条件表达式，提取属性名
      const propNames = this.extractPropsFromExpression(condition);
      
      propNames.forEach(propName => {
        // 检查是否已存在
        const existingProp = props.find(p => p.name === propName);
        if (existingProp) return;
        
        // 创建新属性
        props.push({
          name: propName,
          type: 'boolean', // 条件指令中的属性通常是布尔类型
          description: '',
          required: false,
          values: ['true', 'false']
        });
      });
      
      // 检查条件是否是对属性的值判断
      this.extractPropValuesFromCondition(condition, props);
    });
  }
  
  /**
   * 从循环渲染指令中提取属性信息
   */
  private extractPropsFromLoops(
    templateContent: string, 
    props: ComponentProp[], 
    isVue3: boolean
  ): void {
    // v-for 指令
    const loopMatches = templateContent.match(/v-for\s*=\s*["']([^"']+)["']/g);
    if (!loopMatches) return;
    
    loopMatches.forEach(directive => {
      const match = directive.match(/v-for\s*=\s*["']([^"']+) in ([^"']+)["']/);
      if (!match) return;
      
      const collection = match[2];
      
      // 提取集合名称
      const propName = collection.trim();
      
      // 检查是否已存在
      const existingProp = props.find(p => p.name === propName);
      if (existingProp) {
        // 如果已存在，更新类型为数组
        if (existingProp.type === 'any' || existingProp.type === 'unknown') {
          existingProp.type = 'any[]';
        } else if (!existingProp.type.includes('[]') && !existingProp.type.includes('Array')) {
          existingProp.type = `${existingProp.type}[]`;
        }
      } else {
        // 创建新属性
        props.push({
          name: propName,
          type: 'any[]',
          description: '',
          required: false,
          values: []
        });
      }
    });
  }
  
  /**
   * 从属性绑定中提取属性信息
   */
  private extractPropsFromBindings(
    templateContent: string, 
    props: ComponentProp[], 
    isVue3: boolean
  ): void {
    // v-bind 或 : 绑定
    const bindMatches = templateContent.match(/(?:v-bind:|:)[^=]+\s*=\s*["']([^"']+)["']/g);
    if (!bindMatches) return;
    
    bindMatches.forEach(binding => {
      const match = binding.match(/(?:v-bind:|:)([^=]+)\s*=\s*["']([^"']+)["']/);
      if (!match) return;
      
      const expression = match[2];
      
      // 提取表达式中的属性名
      const propNames = this.extractPropsFromExpression(expression);
      
      propNames.forEach(propName => {
        // 检查是否已存在
        const existingProp = props.find(p => p.name === propName);
        if (existingProp) return;
        
        // 创建新属性
        props.push({
          name: propName,
          type: 'any',
          description: '',
          required: false,
          values: []
        });
      });
    });
  }
  
  /**
   * 从表达式中提取属性名
   */
  private extractPropsFromExpression(expression: string): string[] {
    const propNames: string[] = [];
    
    // 移除所有引号内的内容，避免混淆
    const cleanExpression = expression.replace(/"[^"]*"|'[^']*'|`[^`]*`/g, '');
    
    // 使用正则表达式提取可能的属性名
    const identifierPattern = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g;
    let match;
    
    while ((match = identifierPattern.exec(cleanExpression)) !== null) {
      const identifier = match[1];
      
      // 排除JavaScript关键字和常用操作符
      if (!this.isJavaScriptKeyword(identifier)) {
        propNames.push(identifier);
      }
    }
    
    return propNames;
  }
  
  /**
   * 检查是否为JavaScript关键字
   */
  private isJavaScriptKeyword(word: string): boolean {
    const keywords = [
      'if', 'else', 'switch', 'case', 'break', 'default',
      'for', 'while', 'do', 'continue', 'return',
      'function', 'var', 'let', 'const',
      'new', 'this', 'super', 'class', 'extends',
      'true', 'false', 'null', 'undefined',
      'try', 'catch', 'finally', 'throw',
      'typeof', 'instanceof', 'in', 'of',
      'Math', 'Date', 'Array', 'Object', 'String', 'Number', 'Boolean',
      'console', 'window', 'document'
    ];
    
    return keywords.includes(word);
  }
  
  /**
   * 从条件语句中提取属性的可能值
   */
  private extractPropValuesFromCondition(condition: string, props: ComponentProp[]): void {
    // 常见的相等比较模式: prop === 'value' 或 prop == 'value'
    const equalityMatches = condition.match(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(===|==)\s*(['"])([^'"]+)\3/g);
    if (equalityMatches) {
      equalityMatches.forEach(equality => {
        const match = equality.match(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(===|==)\s*(['"])([^'"]+)\3/);
        if (!match) return;
        
        const propName = match[1];
        const value = match[4];
        
        // 查找对应的属性
        const prop = props.find(p => p.name === propName);
        if (prop) {
          // 初始化values数组（如果需要）
          if (!prop.values) {
            prop.values = [];
          }
          
          // 添加值（如果不存在）
          if (!prop.values.includes(`'${value}'`)) {
            prop.values.push(`'${value}'`);
          }
          
          // 更新类型（如果需要）
          if (prop.type === 'any' || prop.type === 'unknown') {
            prop.type = typeof value === 'number' ? 'number' : 'string';
          }
        }
      });
    }
  }
  
  /**
   * 从模板中提取事件信息
   */
  private extractEventsFromTemplate(
    templateContent: string, 
    events: ComponentEvent[], 
    isVue3: boolean
  ): void {
    // v-on 或 @ 事件绑定
    const eventMatches = templateContent.match(/(?:v-on:|@)[^=]+\s*=\s*["']([^"']+)["']/g);
    if (!eventMatches) return;
    
    eventMatches.forEach(eventBinding => {
      const match = eventBinding.match(/(?:v-on:|@)([^=]+)\s*=\s*["']([^"']+)["']/);
      if (!match) return;
      
      const eventName = match[1].trim();
      
      // 检查是否已存在
      const existingEvent = events.find(e => e.name === eventName);
      if (existingEvent) return;
      
      // 创建新事件
      events.push({
        name: eventName,
        description: `${eventName}事件`,
        arguments: []
      });
    });
  }
  
  /**
   * 分析脚本内容
   */
  private analyzeScript(
    scriptContent: string, 
    result: {
      props: ComponentProp[];
      events: ComponentEvent[];
      slots: ComponentSlot[];
      methods: ComponentMethod[];
    },
    isVue3: boolean
  ): void {
    // 分析方法定义
    this.extractMethodsFromScript(scriptContent, result.methods, isVue3);
    
    // 分析事件触发
    this.extractEmitsFromScript(scriptContent, result.events, isVue3);
    
    // 分析计算属性
    this.extractComputedPropertiesFromScript(scriptContent, result.props, isVue3);
  }
  
  /**
   * 从脚本中提取方法定义
   */
  private extractMethodsFromScript(
    scriptContent: string, 
    methods: ComponentMethod[], 
    isVue3: boolean
  ): void {
    if (isVue3) {
      // Vue 3: 查找函数声明和箭头函数
      const functionMatches = scriptContent.match(/(?:function\s+|const\s+)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(([^)]*)\)/g);
      
      if (functionMatches) {
        functionMatches.forEach(func => {
          const match = func.match(/(?:function\s+|const\s+)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(([^)]*)\)/);
          if (!match) return;
          
          const methodName = match[1];
          const params = match[2];
          
          // 跳过生命周期钩子和内部方法
          if (this.isLifecycleHook(methodName) || methodName.startsWith('_')) {
            return;
          }
          
          // 检查是否已存在
          const existingMethod = methods.find(m => m.name === methodName);
          if (existingMethod) return;
          
          // 创建新方法
          methods.push({
            name: methodName,
            description: '',
            params: this.parseMethodParams(params),
            returns: { type: 'void', description: '' }
          });
        });
      }
    } else {
      // Vue 2: 查找methods对象中的方法
      const methodsMatch = scriptContent.match(/methods\s*:\s*\{([\s\S]*?)\}/);
      if (methodsMatch) {
        const methodsBlock = methodsMatch[1];
        
        // 提取方法定义
        const methodDefMatches = methodsBlock.match(/([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(([^)]*)\)/g);
        
        if (methodDefMatches) {
          methodDefMatches.forEach(methodDef => {
            const match = methodDef.match(/([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(([^)]*)\)/);
            if (!match) return;
            
            const methodName = match[1];
            const params = match[2];
            
            // 检查是否已存在
            const existingMethod = methods.find(m => m.name === methodName);
            if (existingMethod) return;
            
            // 创建新方法
            methods.push({
              name: methodName,
              description: '',
              params: this.parseMethodParams(params),
              returns: { type: 'void', description: '' }
            });
          });
        }
      }
    }
  }
  
  /**
   * 解析方法参数
   */
  private parseMethodParams(paramsString: string): any[] {
    if (!paramsString.trim()) {
      return [];
    }
    
    return paramsString.split(',').map(param => {
      const paramName = param.trim();
      return {
        name: paramName,
        type: 'any',
        description: ''
      };
    });
  }
  
  /**
   * 检查是否为生命周期钩子
   */
  private isLifecycleHook(name: string): boolean {
    const lifecycleHooks = [
      'beforeCreate', 'created',
      'beforeMount', 'mounted',
      'beforeUpdate', 'updated',
      'beforeDestroy', 'destroyed',
      'beforeUnmount', 'unmounted',
      'activated', 'deactivated',
      'errorCaptured', 'renderTracked', 'renderTriggered',
      'setup', 'onMounted', 'onBeforeMount', 'onBeforeUpdate',
      'onUpdated', 'onBeforeUnmount', 'onUnmounted', 'onActivated',
      'onDeactivated', 'onErrorCaptured'
    ];
    
    return lifecycleHooks.includes(name);
  }
  
  /**
   * 从脚本中提取事件触发
   */
  private extractEmitsFromScript(
    scriptContent: string, 
    events: ComponentEvent[], 
    isVue3: boolean
  ): void {
    if (isVue3) {
      // Vue 3: 查找emit()调用
      const emitMatches = scriptContent.match(/emit\s*\(\s*['"]([^'"]+)['"]/g);
      
      if (emitMatches) {
        emitMatches.forEach(emitCall => {
          const match = emitCall.match(/emit\s*\(\s*['"]([^'"]+)['"]/);
          if (!match) return;
          
          const eventName = match[1];
          
          // 检查是否已存在
          const existingEvent = events.find(e => e.name === eventName);
          if (existingEvent) return;
          
          // 创建新事件
          events.push({
            name: eventName,
            description: `${eventName}事件`,
            arguments: []
          });
        });
      }
      
      // 查找defineEmits
      const defineEmitsMatch = scriptContent.match(/defineEmits\s*\(\s*\[\s*([^\]]+)\s*\]\s*\)/);
      if (defineEmitsMatch) {
        const emitsList = defineEmitsMatch[1];
        const emitsMatches = emitsList.match(/['"]([^'"]+)['"]/g);
        
        if (emitsMatches) {
          emitsMatches.forEach(emit => {
            const match = emit.match(/['"]([^'"]+)['"]/);
            if (!match) return;
            
            const eventName = match[1];
            
            // 检查是否已存在
            const existingEvent = events.find(e => e.name === eventName);
            if (existingEvent) return;
            
            // 创建新事件
            events.push({
              name: eventName,
              description: `${eventName}事件`,
              arguments: []
            });
          });
        }
      }
    } else {
      // Vue 2: 查找$emit调用
      const emitMatches = scriptContent.match(/\$emit\s*\(\s*['"]([^'"]+)['"]/g);
      
      if (emitMatches) {
        emitMatches.forEach(emitCall => {
          const match = emitCall.match(/\$emit\s*\(\s*['"]([^'"]+)['"]/);
          if (!match) return;
          
          const eventName = match[1];
          
          // 检查是否已存在
          const existingEvent = events.find(e => e.name === eventName);
          if (existingEvent) return;
          
          // 创建新事件
          events.push({
            name: eventName,
            description: `${eventName}事件`,
            arguments: []
          });
        });
      }
    }
  }
  
  /**
   * 从脚本中提取计算属性
   */
  private extractComputedPropertiesFromScript(
    scriptContent: string, 
    props: ComponentProp[], 
    isVue3: boolean
  ): void {
    if (isVue3) {
      // Vue 3: 查找computed()调用
      const computedMatches = scriptContent.match(/const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*computed\s*\(/g);
      
      if (computedMatches) {
        computedMatches.forEach(computedCall => {
          const match = computedCall.match(/const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*computed\s*\(/);
          if (!match) return;
          
          const propName = match[1];
          
          // 计算属性通常不是props，但可能依赖于props
          // 我们可以分析计算属性的实现，推断其依赖的props
        });
      }
    } else {
      // Vue 2: 查找computed对象
      const computedMatch = scriptContent.match(/computed\s*:\s*\{([\s\S]*?)\}/);
      if (computedMatch) {
        const computedBlock = computedMatch[1];
        
        // 提取计算属性定义
        const computedPropMatches = computedBlock.match(/([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*\{/g);
        
        if (computedPropMatches) {
          computedPropMatches.forEach(propDef => {
            const match = propDef.match(/([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*\{/);
            if (!match) return;
            
            const propName = match[1];
            
            // 同样，我们可以分析计算属性的实现，推断其依赖的props
          });
        }
      }
    }
  }
} 